/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						      checked_cast.h

	$Header: /resource_editor/checked_cast.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( CHECKED_CAST_H_INCLUDED )
#define CHECKED_CAST_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

//------------------------------------------------------------
// checked_cast function template.  Does debug checking with
// dynamic_cast in debug build.
//------------------------------------------------------------

#if defined( NDEBUG )

template < typename t_dest_ptr, typename t_source >
inline t_dest_ptr checked_cast( t_source * source_ptr )
{
	return static_cast< t_dest_ptr >( source_ptr );
}

#else // defined( NDEBUG )

#include <cassert>
#include <typeinfo>

#include "debug_message.h"
#include "format_string.h"

namespace checked_cast_details
{
	template < typename t >
	class t_type_wrapper {};

	template < typename t_dest_ptr, typename t_source >
	void failed( t_type_wrapper< t_dest_ptr >, t_type_wrapper< t_source > )
	{
		DEBUG_MESSAGE( format_string( "checked_cast failed.  Source type: %s,  Dest type: %s", typeid( t_source * ).name(), typeid( t_dest_ptr ).name() ).c_str() );
		assert( false );
	}
}

template < typename t_dest_ptr, typename t_source >
inline t_dest_ptr checked_cast( t_source * source_ptr )
{
	if ( dynamic_cast< t_dest_ptr >( source_ptr ) == 0 )
		checked_cast_details::failed( checked_cast_details::t_type_wrapper< t_dest_ptr >(), checked_cast_details::t_type_wrapper< t_source >() );

	return static_cast< t_dest_ptr >( source_ptr );
}

#endif // defined( NDEBUG )

#endif // !defined( CHECKED_CAST_H_INCLUDED )
